package com.han.spider.safecounty;

import com.han.spider.safecounty.entity.DeviceEntity;
import com.han.spider.safecounty.entity.RegionEntity;
import com.han.util.UnZipper;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Hanjiafeng
 * @Date: 2020/5/23
 * @Desc: 提供HttpClient、HttpRequest.Builder
 */
public class VideoMonitor {
    private final HttpClient httpClient;
    private final HttpRequest.Builder requestBuilder;

    VideoMonitor(String cookie) {
        HttpClient.Builder clientBuilder = HttpClient.newBuilder();
        httpClient = clientBuilder.build();

        requestBuilder = HttpRequest.newBuilder()
                .timeout(Duration.ofMinutes(1))
                .setHeader("Accept", "application/json, text/plain, */*")
                .setHeader("Accept-Encoding", "gzip, deflate, br")
                .setHeader("Accept-Language", "en,zh-CN;q=0.9,zh;q=0.8")
                .setHeader("Content-Type", "application/x-www-form-urlencoded")
                .setHeader("Cookie", cookie)
                .setHeader("Referer", "https://ehome.21cn.com/cameraPlatform/static/index.html")
                .setHeader("Sec-Fetch-Dest", "empty")
                .setHeader("Sec-Fetch-Mode", "cors")
                .setHeader("Sec-Fetch-Site", "same-origin")
                .setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36");
    }

    public HttpClient getHttpClient() {
        return httpClient;
    }

    public HttpRequest.Builder getRequestBuilder() {
        return requestBuilder;
    }

    /**
     * 根据上级区域ID查找出所有下级的id和名称放入Map中
     *
     * @param superiorId 上机区域id
     * @return 区域id
     * @throws IOException          读取异常
     * @throws InterruptedException 中断异常
     */
    Map<String, List<String[]>> selectRegion(String superiorId) throws IOException, InterruptedException {
        HttpRequest.BodyPublisher postData = HttpRequest.BodyPublishers.ofString("selectReginId=" + superiorId);
        HttpRequest httpRequest = requestBuilder
                .uri(URI.create("https://ehome.21cn.com/cameraPlatform/mapi/group/getReginWithGroupListById"))
                .POST(postData)
                .build();

        HttpResponse<byte[]> byteResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
        String body = new String(UnZipper.unGzipByBytes(byteResponse.body()), StandardCharsets.UTF_8);

        Map<String, List<String[]>> regionMap = new HashMap<>(16);
        regionMap.put(superiorId, parseBody(body));
        return regionMap;
    }

    /**
     * 解析body里的id和name放入regionMap中
     *
     * @param body body
     * @return 区域map
     */
    List<String[]> parseBody(String body) {
        List<String[]> regionList = new ArrayList<>();
        JSONObject jsonObject = new JSONObject(body);
        try {
            JSONArray jsonArray = jsonObject.getJSONArray("reginWithGroupList");
            for (int i = 0; i < jsonArray.length(); i++) {
                try {
                    JSONObject regionJson = jsonArray.getJSONObject(i);
                    String reginCode = regionJson.getString("reginCode");
                    int level = regionJson.getInt("level");
                    if (!(level == 3 && !reginCode.isEmpty())) {
                        String regionId = regionJson.getInt("id") + "";
                        String regionName = regionJson.getString("name");
                        regionList.add(new String[]{regionId, regionName});
                    }
                } catch (JSONException e) {
                    System.out.println(e.getMessage() + "_1:" + body);
                }
            }
        } catch (JSONException e) {
            System.out.println(e.getMessage() + "_2:" + body);
        }

        return regionList;
    }

    /**
     * 根据上级区域ID查找出所有下级的id和名称放入Map中
     *
     * @param parentRegionEntity 区域实体
     * @return 区域id
     * @throws IOException          读取异常
     * @throws InterruptedException 中断异常
     */
    Map<Integer, RegionEntity> selectRegionNew(RegionEntity parentRegionEntity) throws IOException, InterruptedException {
        HttpRequest.BodyPublisher postData = HttpRequest.BodyPublishers.ofString("selectReginId=" + parentRegionEntity.getId() + "&level=" + parentRegionEntity.getLevelEnum().getId());
        HttpRequest httpRequest = requestBuilder
                .uri(URI.create("https://ehome.21cn.com/cameraPlatform/mapi/group/getReginWithGroupListById"))
                .POST(postData)
                .build();

        HttpResponse<byte[]> byteResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
        String body = new String(UnZipper.unGzipByBytes(byteResponse.body()), StandardCharsets.UTF_8);

        return parseRegionBodyNew(parentRegionEntity, body);
    }

    Map<String, DeviceEntity> selectDevice(RegionEntity parentRegionEntity) throws IOException, InterruptedException {
        HttpRequest.BodyPublisher postData = HttpRequest.BodyPublishers.ofString("groupId=" + parentRegionEntity.getId());
        HttpRequest httpRequest = requestBuilder
                .uri(URI.create("https://ehome.21cn.com/cameraPlatform/mapi/device/getDeviceList"))
                .POST(postData)
                .build();

        HttpResponse<byte[]> byteResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
        String body = new String(UnZipper.unGzipByBytes(byteResponse.body()), StandardCharsets.UTF_8);

        return parseDeviceBody(parentRegionEntity, body);
    }

    /**
     * 解析区域body
     *
     * @param parentRegionEntity 父区域实体
     * @param body               解析字符串
     * @return 解析出的区域实体map->(区域id,区域实体)
     */
    Map<Integer, RegionEntity> parseRegionBodyNew(RegionEntity parentRegionEntity, String body) {
        Map<Integer, RegionEntity> regionEntityMap = new HashMap<>(5);
        JSONObject jsonObject = new JSONObject(body);
        List<Integer> childrenIdList = new ArrayList<>();
        try {
            JSONArray jsonArray = jsonObject.getJSONArray("reginWithGroupList");
            for (int i = 0; i < jsonArray.length(); i++) {
                try {
                    JSONObject regionJson = jsonArray.getJSONObject(i);
                    int level = regionJson.getInt("level");
                    int regionId = regionJson.getInt("id");
                    String regionName = regionJson.getString("name");
                    LevelEnum levelEnum;
                    if (level == 0) {
                        levelEnum = LevelEnum.XIAN;
                    } else if (level == 1) {
                        levelEnum = LevelEnum.ZHEN;
                    } else if (level == 2) {
                        levelEnum = LevelEnum.CUN;
                    } else if (level == 3) {
                        levelEnum = LevelEnum.ZHUANG;
                    } else {
                        levelEnum = LevelEnum.OTHER;
                    }
                    int type = regionJson.getInt("type");
                    TypeEnum typeEnum;
                    if (type == 1) {
                        typeEnum = TypeEnum.NO_DIRECT_DEVICE;
                    } else if (type == 2) {

                        typeEnum = TypeEnum.DIRECT_DEVICE;
                    } else {
                        typeEnum = TypeEnum.OTHER;
                    }
                    String regionCode = regionJson.getString("reginCode");
                    //添加区域id
                    childrenIdList.add(regionId);
                    RegionEntity regionEntity = new RegionEntity(regionId, regionName, levelEnum, typeEnum, parentRegionEntity.getId(), null, null, regionCode);
                    regionEntityMap.put(regionId, regionEntity);
                } catch (JSONException e) {
                    System.out.println(e.getMessage() + "_1:" + body);
                }
            }
            Integer[] childrenIds = childrenIdList.toArray(new Integer[0]);
            parentRegionEntity.setNextIds(childrenIds);
        } catch (JSONException e) {
            System.out.println(e.getMessage() + "_2:" + body);
        }
        return regionEntityMap;
    }

    /**
     * 解析设备组
     *
     * @param parentRegionEntity 区域实体
     * @param body               设备组
     * @return 设备组
     */
    Map<String, DeviceEntity> parseDeviceBody(RegionEntity parentRegionEntity, String body) {
        Map<String, DeviceEntity> deviceEntityMap = new HashMap<>(5);
        try {
            JSONObject jsonObject = new JSONObject(body);
            List<String> deviceCodeList = new ArrayList<>();
            try {
                JSONArray jsonArray = jsonObject.getJSONArray("deviceList");
                for (int i = 0; i < jsonArray.length(); i++) {
                    try {
                        JSONObject regionJson = jsonArray.getJSONObject(i);
                        String code = regionJson.getString("deviceCode");
                        String name = regionJson.getString("deviceName");
                        String model = regionJson.getString("deviceModel");
                        DeviceEntity deviceEntity = new DeviceEntity(code, name, parentRegionEntity.getId(), model);
                        deviceEntityMap.put(code, deviceEntity);
                        //添加区域id
                        deviceCodeList.add(code);
                    } catch (JSONException e) {
                        System.out.println(e.getMessage() + "_parseDeviceBody_1:" + body);
                    }
                }
                String[] deviceCodes = deviceCodeList.toArray(new String[0]);
                parentRegionEntity.setDeviceIds(deviceCodes);
            } catch (JSONException e) {
                System.out.println(e.getMessage() + "_parseDeviceBody_2:" + body);
            }
        } catch (JSONException e) {
            System.out.println(e.getMessage() + "_parseDeviceBody_3:" + body);
        }
        return deviceEntityMap;
    }
}
